home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 4 / PC World Interactive 4.iso / online / appbar.EXE / cppsrc / AppBar.cpp < prev    next >
C/C++ Source or Header  |  1996-09-15  |  20KB  |  722 lines

  1. // *********************************************************
  2. // AppBar -- Advanced Menu bar for Windows 95/NT
  3. // All code Copyright (C) 1995, 1996 by Mike Perham
  4. // mperham@cs.cornell.edu
  5. // 
  6. // This code MAY NOT be used for any other program without
  7. // my permission and is forbidden in any shareware/commercial
  8. // program.  This code is provided for educational use only
  9. // and there are no guarantees or promises implied.  Blah blah
  10. // *********************************************************
  11.  
  12. ///////////////////////////////////////////////////////////////////////
  13. // AppBar - the Application behind the window
  14. //              This file encapsulates all I/O, Registry functions, 
  15. //              initialization, etc.
  16. /////////////
  17. //
  18. //      Known Bugs:
  19. //
  20. //               Screen saver will not activate in Win95 unless
  21. //                      AppBar is autohidden.  This must be a problem with
  22. //                      Win95, since it works in all cases under NT4.
  23. //
  24. //               Buttons in Edit Dialog are always gray.  If
  25. //                      you change the default color of your dialogs,
  26. //                      they will stick out like a sore thumb.  This is
  27. //                      because bitmaps do not have a transparent color
  28. //                      unlike icons (which is what the C version uses).
  29. //
  30.  
  31. #include "appbar.h"
  32. #include "globals.h"
  33.  
  34. #ifdef _DEBUG
  35.     #undef THIS_FILE
  36.     static char THIS_FILE[] = __FILE__;
  37.     #define new DEBUG_NEW
  38. #endif
  39.  
  40. ///////////////////////////////////////////////////
  41. // Here it is...
  42.  
  43. AppBar ab;
  44.  
  45. ///////////////////////////////////////////////////
  46. // global variables visible in all classes
  47.  
  48. menu_struct *glob_menu;                         // "2D" list of menus and apps
  49. sys_vars sv;
  50. user_vars uv;                                           // variables set in OptDlg
  51. app_list *applist;                                      // linear list of all apps
  52. APPBARDATA abd;
  53.  
  54. ///////////////////////////////////////////////////
  55. // Creates the AppBar window
  56. /////////
  57.  
  58. BOOL AppBar::ShowAppBar(void)
  59. {
  60.     abwin = new AppBarWin;
  61.     int flags = (uv.stayontop ? WS_EX_TOPMOST : 0) | WS_EX_TOOLWINDOW;
  62.     abwin->CreateEx(flags, (LPCTSTR) ABClass, "AppBar",
  63.                     WS_POPUP | WS_DLGFRAME, 0,
  64.                     (uv.bottom ? sv.height - AB_HEIGHT : 0),
  65.                     AB_WIDTH, AB_HEIGHT, 0, 0, 0);
  66.     if (!abwin->m_hWnd)
  67.         return FALSE;
  68.  
  69.     CWinThread::m_pMainWnd = abwin;
  70.  
  71.     abwin->ShowWindow(SW_SHOW);
  72.     if (sv.newshell)
  73.         if (uv.autohide)
  74.             abwin->HideAppBar(TRUE);
  75.           else
  76.             abwin->ModifyTime();
  77.       else
  78.         abwin->HideAppBar(TRUE);
  79.     return TRUE;
  80. }
  81.  
  82. //////////////////////////////////////////////////
  83. // Set system vars and parse cmd args and get reg keys
  84. // This is the first function executed when AppBar is started
  85. ////////
  86.     
  87. BOOL AppBar::InitApplication(void)
  88. {
  89.     HWND OldWnd = FindWindow(NULL, "AppBar");
  90.     if (OldWnd) {
  91.         BringWindowToTop(OldWnd);
  92.         return FALSE;
  93.     }
  94.  
  95. #ifdef _DEBUG
  96.     begin.Checkpoint();                     // Begin debug memory trace
  97. #endif
  98.  
  99. /*  //This does not compile for some unknown reason
  100.     OSVERSIONINFO ovi;
  101.     ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO)
  102.     GetVersionEx((LPOSVERSIONINFO)&ovi);
  103.     switch (ovi.dwPlatformId) {
  104.         case VER_PLATFORM_WIN32_WINDOWS:
  105.             sv.newshell = TRUE;
  106.             sv.power = FALSE;
  107.             break;
  108.         case VER_PLATFORM_WIN32_NT:
  109.             if (ovi.dwMajorVersion == 4) {
  110.                 sv.newshell = TRUE;
  111.                 sv.power = FALSE;
  112.               } else if (ovi.dwMajorVersion == 3) {
  113.                 sv.newshell = FALSE;
  114.                 sv.power = FALSE;
  115.               } else {
  116.                 sv.newshell = TRUE;
  117.                 sv.power = TRUE;
  118.             }
  119.             break;
  120.         default:
  121.             return FALSE;
  122.     }
  123.   */
  124.  
  125.     DWORD dwVersion = GetVersion();
  126.     DWORD dwMajor =  (DWORD)(LOBYTE(LOWORD(dwVersion)));
  127.     DWORD dwMinor =  (DWORD)(HIBYTE(LOWORD(dwVersion)));
  128.  
  129.     if (dwVersion < 0x80000000) {               // Windows NT
  130.         if (dwMajor == 3) {
  131.             sv.newshell = FALSE;
  132.             sv.power = FALSE;
  133.           } else if (dwMajor == 4) {
  134.             sv.newshell = TRUE;
  135.             sv.power = FALSE;
  136.           } else {      // NT5!
  137.             sv.newshell = TRUE;
  138.             sv.power = TRUE;
  139.         }
  140.     } else if (dwMajor < 4)        // Win32s
  141.         return FALSE;
  142.       else {        // Windows 95 -- No build numbers provided
  143.         sv.newshell = TRUE;
  144.         sv.power = TRUE;
  145.     }
  146.  
  147.     if (sv.power) {
  148.         SYSTEM_POWER_STATUS sps;
  149.         GetSystemPowerStatus(&sps);
  150.         if (sps.ACLineStatus)
  151.             sv.battery = FALSE;
  152.           else
  153.             sv.battery = TRUE;
  154.     }
  155.  
  156.     sv.width = GetSystemMetrics(SM_CXSCREEN);
  157.     sv.height = GetSystemMetrics(SM_CYSCREEN);
  158.  
  159.     // copy AppBar's directory to origdir
  160.     char *end = strrchr(m_pszHelpFilePath, '\\');
  161.     char *front = (char *) m_pszHelpFilePath;
  162.     char *copy = origdir;
  163.  
  164.     while (front != end) {
  165.         *copy = *front;
  166.         copy++; front++;
  167.     }
  168.     *copy = '\0';
  169.  
  170.     SetRegistryKey("Software\\AppBar");
  171.     // parse args AND get registry keys
  172.     ParseCmdArgs();
  173.  
  174.     LPCTSTR temp;
  175.     temp = AfxRegisterWndClass(NULL, NULL, (HBRUSH)COLOR_MENU+1, LoadIcon(IDI_APPBAR));
  176.     ABClass = CString(temp);
  177.     return TRUE;
  178. }
  179.  
  180. BOOL AppBar::InitInstance()
  181. {
  182.     if (!ReadInApps())
  183.         return FALSE;
  184.     return ShowAppBar();
  185. }
  186.  
  187. //////////////////////////
  188. // Reads in the user spec'd applications
  189.  
  190. BOOL AppBar::ReadInApps(void)
  191. {               
  192.     FILE *appfile;
  193.     int i, j=0, ver;
  194.     BOOL exist = TRUE;
  195.     char msg[80];
  196.     menu_struct *cur_menu, *nextmenu, *prevmenu;
  197.     app_struct *cur_app, *nextapp, *prevapp;
  198.  
  199.     // Create binary data file if none exists                            
  200.  
  201.     _chdir(origdir);
  202.     if ((appfile = fopen(sv.appfile, "r")) == NULL)
  203.         exist = FALSE;
  204.                                              
  205.     // Read application data until the end of the file
  206.     // this tests for zero-length data files (exist, but are empty)
  207.     if (exist)
  208.         if (_filelength(_fileno(appfile)) == 0)
  209.             exist = FALSE;
  210.  
  211.     glob_menu = NULL;
  212.     if (exist) {
  213.         fread(&ver, sizeof(int), 1, appfile);
  214.         if (ver != APPBAR_FILE_VERSION) {
  215.             error(OLD_DATAFILE_FORMAT);
  216.             return FALSE;
  217.         }
  218.         cur_menu = new menu_struct;
  219.         glob_menu = cur_menu;
  220.         nextmenu = cur_menu;
  221.         prevmenu = NULL;
  222.         while (fread(nextmenu, sizeof(menu_struct), 1, appfile)) {
  223.             j++;
  224.             cur_menu = nextmenu;
  225.             cur_menu->nextapp = NULL;
  226.             prevapp = NULL;
  227.             cur_menu->prevmenu = prevmenu;
  228.             if (nextmenu->numapps) {
  229.                 cur_app = new app_struct;
  230.                 cur_menu->nextapp = cur_app;
  231.                 for (i=cur_menu->numapps;i>0; i--) {
  232.                     if (!fread(cur_app, sizeof(app_struct), 1, appfile)) {
  233.                         sprintf(msg, ERROR_READING_MENUS,j,
  234.                                 cur_menu->numapps - i + 1, sv.appfile);
  235.                         error(msg);
  236.                     }
  237.                     cur_app->prevapp = prevapp;
  238.                     prevapp = cur_app;
  239.                     if (i-1) {
  240.                         cur_app->nextapp = new app_struct;
  241.                         cur_app = cur_app->nextapp;
  242.                       } else cur_app->nextapp = NULL;
  243.                 }
  244.             }
  245.             prevmenu = cur_menu;
  246.             nextmenu = new menu_struct;
  247.             nextmenu->prevmenu = cur_menu;
  248.             cur_menu->nextmenu = nextmenu;
  249.         }
  250.         // Reached EOF.  Now we need to delete that last menu, since it was
  251.         // created before we knew it was EOF.
  252.         delete nextmenu;
  253.         cur_menu->nextmenu = NULL;
  254.         fclose(appfile);
  255.     } else {
  256.         // Create default menu structure if no datafile exists
  257.         char path[80];
  258.         menu_struct *tempmenu;
  259.  
  260.         tempmenu = new menu_struct;
  261.         strcpy(tempmenu->menuname,"&Apps");
  262.         tempmenu->numapps = 2;
  263.  
  264.         tempmenu->nextapp = new app_struct;
  265.         strcpy(tempmenu->nextapp->appexe, "c:\\vc40\\bin\\msdev.exe");
  266.         strcpy(tempmenu->nextapp->appname, "Visual &C++ v4.0");
  267.         cur_app = tempmenu->nextapp;
  268.  
  269.         nextapp = new app_struct;
  270.         cur_app->nextapp = nextapp;
  271.         nextapp->prevapp = cur_app;
  272.         strcpy(nextapp->appexe, "c:\\winword\\winword.exe");
  273.         strcpy(nextapp->appname, "&Word v7.0");
  274.         glob_menu = tempmenu;
  275.  
  276.         tempmenu = new menu_struct;
  277.         glob_menu->nextmenu = tempmenu;
  278.         tempmenu->prevmenu = glob_menu;
  279.         strcpy(tempmenu->menuname,"&Games");
  280.         tempmenu->numapps = 2;
  281.         
  282.         tempmenu->nextapp = new app_struct;
  283.         GetWindowsDirectory(path, sizeof(path));
  284.         strcat(path,"\\winmine.exe");
  285.         strcpy(tempmenu->nextapp->appexe, path);
  286.         strcpy(tempmenu->nextapp->appname, "&Minesweeper");
  287.         cur_app = tempmenu->nextapp;
  288.  
  289.         nextapp = new app_struct;
  290.         cur_app->nextapp = nextapp;
  291.         nextapp->prevapp = cur_app;
  292.         GetWindowsDirectory(path, sizeof(path));
  293.         strcat(path,"\\sol.exe");
  294.         strcpy(nextapp->appexe, path);
  295.         strcpy(nextapp->appname, "&Solitaire");
  296.     }
  297.     return TRUE;
  298. }                                 
  299.  
  300. //////////////////////////////////////////////////
  301. // Exit function for appbar
  302.  
  303. void AppBar::ExitAppBar(BOOL error_exit)
  304. {
  305.     if (!error_exit) {  // if error, just bomb out...
  306.         SaveMenu();
  307.         SaveRegKey();
  308.         release_app_memory();
  309.     }
  310.     CleanUp();
  311.     PostQuitMessage(0);
  312. }   
  313.  
  314. //////////////////////////////////////////////////
  315. // Delete and unregister all variables and structs
  316.     
  317. void AppBar::CleanUp(void)
  318. {
  319.     if (abwin) {
  320.         if (sv.newshell) {
  321.             abd.cbSize = sizeof(APPBARDATA);
  322.             abd.hWnd = abwin->GetSafeHwnd();
  323.             abd.uEdge = (uv.bottom ? ABE_BOTTOM : ABE_TOP);
  324.             abd.lParam = FALSE;
  325.             SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd);
  326.             SHAppBarMessage(ABM_REMOVE, &abd);
  327.         }
  328.         abwin->DestroyWindow();
  329.         delete abwin;
  330.     }
  331.     UnregisterClass((LPCTSTR)ABClass, m_hInstance);
  332.  
  333. #ifdef _DEBUG
  334.     end.Checkpoint();                               // end memory trace and print stats
  335.     diff.Difference(begin, end);
  336.     diff.DumpStatistics();
  337. #endif
  338. }
  339.                             
  340. //////////////////////////////////////////////////
  341. // Execute application pointed to by app
  342.  
  343. BOOL AppBar::ExecuteApplication(app_struct * app)
  344. {
  345.     char msg[200];
  346.     DWORD error;
  347.  
  348.     if (sv.newshell) {
  349.         SHELLEXECUTEINFO sei;
  350.  
  351.         sei.cbSize = sizeof(SHELLEXECUTEINFO);
  352.         sei.fMask = SEE_MASK_DOENVSUBST | SEE_MASK_NOCLOSEPROCESS;
  353.         sei.hwnd = abwin->m_hWnd;
  354.         sei.lpVerb = "open";
  355.         sei.lpFile = app->appexe;
  356.         sei.lpParameters = app->params;
  357.         sei.lpDirectory = app->workingdir;
  358.         sei.nShow = app->show;
  359.  
  360.         ShellExecuteEx(&sei);
  361. /*                      error = GetLastError();
  362.             switch (error) {
  363.                 case ERROR_FILE_NOT_FOUND:
  364.                     sprintf(msg, FILE_NOT_FOUND, app->appexe);
  365.                     break;
  366.                 case ERROR_PATH_NOT_FOUND:
  367.                     sprintf(msg, PATH_NOT_FOUND, app->appexe);
  368.                     break;
  369.                 case ERROR_NOT_ENOUGH_MEMORY:
  370.                     sprintf(msg, OUT_OF_MEM);
  371.                     break;
  372.                 case ERROR_DLL_NOT_FOUND:
  373.                     sprintf(msg, DLL_NOT_FOUND);
  374.                     break;
  375.                 default:
  376.                     sprintf(msg, RETURNED_ERROR, error);
  377.                     break;
  378.             }
  379.             ab_message(msg, abwin->GetSafeHwnd());
  380.             return 0;
  381.         }*/
  382.     } else {
  383.         error = (DWORD) ShellExecute(abwin->m_hWnd, "open", app->appexe,
  384.                                     app->params, app->workingdir, app->show);
  385.         if (error < 32) {
  386.             switch (error) {
  387.                 case ERROR_FILE_NOT_FOUND:
  388.                     sprintf(msg, FILE_NOT_FOUND, app->appexe);
  389.                     break;
  390.                 case ERROR_PATH_NOT_FOUND:
  391.                     sprintf(msg, PATH_NOT_FOUND, app->appexe);
  392.                     break;
  393.                 default:
  394.                     sprintf(msg, RETURNED_ERROR, error);
  395.                     break;
  396.             }
  397.             ab_message(msg, abwin->GetSafeHwnd());
  398.             return 0;
  399.         }
  400.     }
  401.     return 1;
  402. }
  403.  
  404. //////////////////////////////////////////////////
  405. // it's hideous, but it does the job...
  406.  
  407. void AppBar::ParseCmdArgs(void)
  408. {
  409.     char msg[80];
  410.     int j;
  411.     user_vars args;
  412.     BOOL done = FALSE;
  413.  
  414.     strcpy(sv.user, "");
  415.     strcpy(sv.appfile, "");
  416.     memset((void*)&args, 0, sizeof(user_vars));
  417.     // now process the array of parameters
  418.     for (j=1;j<__argc;j++) {
  419.         if (!strncmp(__argv[j], "-", 1)) {
  420.             if (!strncmp((char*)__argv[j]+1, "s", 1))
  421.                 args.stayontop = -1;
  422.               else if (!strncmp((char*)__argv[j]+1, "c", 1))
  423.                 args.chime = -1;
  424.               else if (!strncmp((char*)__argv[j]+1, "b", 1))
  425.                 args.bottom = -1;
  426.               else if (!strncmp((char*)__argv[j]+1, "a", 1))
  427.                 args.autohide = -1;
  428.               else if (!strncmp((char*)__argv[j]+1, "d", 1))
  429.                 args.date = -1;
  430.               else if (!strncmp((char*)__argv[j]+1, "m", 1))
  431.                 args.memory = -1;
  432.               else if (!strncmp((char*)__argv[j]+1, "t", 1))
  433.                 args.time = -1;
  434.               else if (!strncmp((char*)__argv[j]+1, "u", 1))
  435.                 args.user = -1;
  436.               else if (!strncmp((char*)__argv[j]+1, "f", 1)) {
  437.                 if ((j+1 <= __argc)) {
  438.                     char w = *(__argv[j+1]);
  439.                     // if filename does not start with '-' or '+'
  440.                     // assume it is a valid filename
  441.                     if (!((w == '+') || (w == '-')))
  442.                         strcpy((char *)sv.appfile, __argv[++j]);
  443.                       else {
  444.                         j++;
  445.                         ab_message(INVALID_FILENAME, abwin->GetSafeHwnd());
  446.                     }
  447.                 } else
  448.                     ab_message(INVALID_FILENAME, abwin->GetSafeHwnd());
  449.               } else {
  450.                 sprintf(msg, UNKNOWN_OPTION, __argv[j]);
  451.                 ab_message(msg, abwin->GetSafeHwnd());
  452.             }
  453.         } else if (!strncmp(__argv[j], "+", 1)) {
  454.             if (!strncmp((char*)__argv[j]+1, "s", 1))
  455.                 args.stayontop = 1;
  456.               else if (!strncmp((char*)__argv[j]+1, "c", 1))
  457.                 args.chime = 1;
  458.               else if (!strncmp((char*)__argv[j]+1, "a", 1))
  459.                 args.autohide = 1;
  460.               else if (!strncmp((char*)__argv[j]+1, "b", 1))
  461.                 args.bottom = 1;
  462.               else if (!strncmp((char*)__argv[j]+1, "d", 1))
  463.                 args.date = 1;
  464.               else if (!strncmp((char*)__argv[j]+1, "m", 1))
  465.                 args.memory = 1;
  466.               else if (!strncmp((char*)__argv[j]+1, "t", 1))
  467.                 args.time = 1;
  468.               else if (!strncmp((char*)__argv[j]+1, "u", 1))
  469.                 args.user = 1;
  470.               else if (!strncmp((char*)__argv[j]+1, "f", 1)) {
  471.                 if ((j+1 <= __argc)) {
  472.                     char w = *(__argv[j+1]);
  473.                     if (!((w == '+') || (w == '-')))
  474.                         strcpy((char *)sv.appfile, __argv[++j]);
  475.                       else {
  476.                         j++;
  477.                         ab_message(INVALID_FILENAME, abwin->GetSafeHwnd());
  478.                     }
  479.                 } else
  480.                     ab_message(INVALID_FILENAME, abwin->GetSafeHwnd());
  481.               } else {
  482.                 sprintf(msg, UNKNOWN_OPTION, __argv[j]);
  483.                 ab_message(msg, abwin->GetSafeHwnd());
  484.             }
  485.         } else      // User gave a user configuration
  486.             strcpy((char*)sv.user, __argv[j]);
  487.     } // end while
  488.  
  489.     if (strcmp((char*)sv.user, ""))
  490.         sprintf(sv.appfile, "appbar.%s", sv.user);
  491.  
  492.     GetRegKeys(&args);
  493. }
  494.  
  495. //////////////////////////////////////////////////
  496.  
  497. #define SET(a); if (args->a == 1) \
  498.                     uv.a = TRUE; \
  499.                  else if (args->a == -1) \
  500.                     uv.a = FALSE;
  501.  
  502. void AppBar::GetRegKeys(user_vars *args)
  503. {
  504.     HKEY root;
  505.     DWORD isnew, type, size = sizeof(user_vars);
  506.     LONG rc;
  507.     char *p, keyname[80], mike[80];
  508.  
  509.     // each user gets his own key in the registry
  510.     if (strlen(sv.user)) {
  511.         strcpy(mike, sv.user);
  512.         // this loop will not work with Unicode
  513.         for (p=mike; p<mike+strlen(mike); p++)
  514.             _tolower(*p);
  515.         sprintf(keyname, "%s\\%s", m_pszRegistryKey, mike);
  516.     } else
  517.         sprintf(keyname, "%s\\Default", m_pszRegistryKey);
  518.  
  519.  
  520.     if (!strcmp(sv.appfile, ""))
  521.         strcpy(sv.appfile, "appbar.default");
  522.     // create or open key
  523.     rc = RegCreateKeyEx(HKEY_CURRENT_USER, keyname, 0, NULL,
  524.                     REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  525.                     NULL, &root, &isnew);
  526.     
  527.     if (rc != ERROR_SUCCESS) {
  528.         ab_message(ERROR_OPENING_REG, abwin->GetSafeHwnd());
  529.         uv.stayontop = TRUE;
  530.         uv.time = TRUE;
  531.         uv.memory = TRUE;
  532.         uv.autohide = TRUE;
  533.         uv.chime = FALSE;
  534.         uv.date = FALSE;
  535.         uv.bottom = FALSE;
  536.         uv.user = FALSE;
  537.         strcpy(uv.wavfile, "");
  538.         if (strlen(sv.user))
  539.             sprintf(sv.appfile, "appbar.%s", sv.user);
  540.           else
  541.             strcpy(sv.appfile, "appbar.default");
  542.         return;
  543.     }
  544.     
  545.     if (isnew != REG_OPENED_EXISTING_KEY)
  546.         MakeNewRegKey(root);
  547.       else {
  548.         rc = RegQueryValueEx(root, "User_Variables", NULL, &type, (PBYTE)&uv, &size);
  549.         if (size != sizeof(user_vars)) {
  550.             ab_message(OBSOLETE_REG_DATA, abwin->GetSafeHwnd());
  551.             RegDeleteKey(root, "User_Variables");
  552.             MakeNewRegKey(root);
  553.         }
  554.     }
  555.     RegCloseKey(root);
  556.         // modify user vars according to cmd args
  557.     SET(date);
  558.     SET(memory);
  559.     SET(stayontop);
  560.     SET(bottom);
  561.     SET(autohide);
  562.     SET(chime);
  563.     SET(time);
  564.     SET(user);
  565.  
  566.     if (!sv.newshell)
  567.         uv.autohide = TRUE;                  // autohide is ALWAYS on in WinNT 3
  568. }
  569.  
  570. //////////////////////////////////////////////////
  571.  
  572. void AppBar::MakeNewRegKey(HKEY root)
  573. {
  574.     char msg[100];
  575.     char comma[3] = "";
  576.     LONG rc;
  577.  
  578.     if (strcmp(sv.user, ""))
  579.         strcpy(comma, ", ");
  580.     sprintf(msg, WELCOME_MSG, comma, sv.user);
  581.     ab_message(msg, abwin->GetSafeHwnd());
  582.     uv.time = TRUE;
  583.     uv.stayontop = TRUE;
  584.     uv.chime = FALSE;
  585.     uv.date = FALSE;
  586.     uv.user = FALSE;
  587.     uv.bottom = FALSE;
  588.     uv.memory = TRUE;
  589.     uv.autohide = TRUE;
  590.     strcpy(uv.wavfile, "");
  591.     rc = RegSetValueEx(root, "User_Variables", NULL, REG_BINARY, 
  592.                 (PBYTE) &uv, sizeof(user_vars));
  593.     if (rc != ERROR_SUCCESS)
  594.         ab_message(ERROR_SAVING_REG, abwin->GetSafeHwnd());
  595. }
  596.  
  597. //////////////////////////////////////////////////
  598.  
  599. void AppBar::SaveRegKey(void)
  600. {
  601.     HKEY root;
  602.     char keyname[80];
  603.     DWORD isnew;
  604.  
  605.     if (strcmp((char*)sv.user, ""))
  606.         sprintf(keyname, "%s\\%s", m_pszRegistryKey, sv.user);
  607.       else
  608.         sprintf(keyname, "%s\\Default", m_pszRegistryKey);
  609.  
  610.     if (RegCreateKeyEx(HKEY_CURRENT_USER, keyname, 0, NULL,
  611.                 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &root, &isnew))
  612.         ab_message(ERROR_SAVING_REG, abwin->GetSafeHwnd());
  613.     if (RegSetValueEx(root, "User_Variables", NULL, REG_BINARY, 
  614.                 (PBYTE)&uv, sizeof(user_vars)))
  615.         ab_message(ERROR_SAVING_REG, abwin->GetSafeHwnd());
  616.     RegCloseKey(root);
  617. }
  618.  
  619. void AppBar::SaveMenu(void)
  620. {
  621.     app_struct * pCurApp;
  622.     menu_struct * pCurMenu;
  623.     app_struct *next, *prev, *nexta;
  624.     menu_struct *nextm, *prevm;
  625.     char msg[80];
  626.     FILE *pDataFile;
  627.     int i;
  628.  
  629.     _chdir(origdir);
  630.     pDataFile = fopen(sv.appfile, "wb");      // Open for binary write
  631.  
  632.     if (!pDataFile) {
  633.         sprintf(msg, ERROR_OPENING_DATAFILE, sv.appfile);
  634.         ab_message(msg, abwin->GetSafeHwnd());
  635.         return;
  636.     }
  637.     
  638.     i = APPBAR_FILE_VERSION;
  639.     fwrite(&i, sizeof(int), 1, pDataFile);
  640.     for (pCurMenu = glob_menu; pCurMenu != NULL; pCurMenu = pCurMenu->nextmenu) {
  641.         nextm = pCurMenu->nextmenu;
  642.         prevm = pCurMenu->prevmenu;
  643.         nexta = pCurMenu->nextapp;
  644.         pCurMenu->nextapp = NULL;
  645.         pCurMenu->nextmenu = NULL;
  646.         pCurMenu->prevmenu = NULL;
  647.         fwrite(pCurMenu, sizeof(menu_struct), 1, pDataFile);
  648.         pCurMenu->nextapp = nexta;
  649.         pCurMenu->nextmenu = nextm;
  650.         pCurMenu->prevmenu = prevm;
  651.         for (pCurApp = pCurMenu->nextapp; pCurApp != NULL; pCurApp = pCurApp->nextapp) {
  652.             next = pCurApp->nextapp;
  653.             prev = pCurApp->prevapp;
  654.             pCurApp->nextapp = NULL;
  655.             pCurApp->prevapp = NULL;
  656.             fwrite(pCurApp, sizeof(app_struct), 1, pDataFile);
  657.             pCurApp->nextapp = next;
  658.             pCurApp->prevapp = prev;
  659.         }
  660.     }
  661.     fclose(pDataFile);
  662. }
  663.  
  664. ///////////////////////////////////////////////////////////////////////////
  665. //  C++ Constructors and Destructors                                     //
  666. ///////////////////////////////////////////////////////////////////////////
  667.  
  668. menu_struct::menu_struct()
  669. {
  670.     memset((void*)menuname, 0, sizeof(menuname));
  671.     numapps = 0;
  672.     nextmenu = NULL;
  673.     prevmenu = NULL;
  674.     nextapp = NULL;
  675. }
  676.  
  677. menu_struct::~menu_struct()
  678. {
  679.     if (nextmenu == NULL) {
  680.         if (prevmenu != NULL)
  681.             prevmenu->nextmenu = NULL;
  682.           else
  683.             glob_menu = NULL;
  684.       } 
  685.     else if (prevmenu == NULL) {
  686.         glob_menu = nextmenu;
  687.         nextmenu->prevmenu = NULL;
  688.       } 
  689.     else {
  690.         if (prevmenu)
  691.             prevmenu->nextmenu = nextmenu;
  692.         if (nextmenu) 
  693.             nextmenu->prevmenu = prevmenu;
  694.     }
  695. }
  696.  
  697. app_struct::app_struct()
  698. {
  699.     memset((void*)appexe, 0, sizeof(appexe));
  700.     memset((void*)workingdir, 0, sizeof(workingdir));
  701.     memset((void*)params, 0, sizeof(params));
  702.     memset((void*)appname, 0, sizeof(appname));
  703.     show = 0;
  704.     separator = FALSE;
  705.     nextapp = NULL;
  706.     prevapp = NULL;
  707. }
  708.  
  709. app_struct::~app_struct()
  710. {
  711.     if (nextapp == NULL) {
  712.         if (prevapp != NULL)
  713.             prevapp->nextapp = NULL;
  714.       } 
  715.     else if (prevapp == NULL)
  716.         nextapp->prevapp = NULL;
  717.     else {
  718.         prevapp->nextapp = nextapp;
  719.         nextapp->prevapp = prevapp;
  720.     }
  721. }
  722.